package com.zyf.workflow.node;


import com.zyf.workflow.exception.ArrangeException;
import com.zyf.workflow.node.bean.NodeResultBean;
import com.zyf.workflow.node.bean.NodeType;
import com.zyf.workflow.worker.Worker;


public class WorkNode<T, P> implements Node<P> {

    private T data;
    private Worker<T, P, ?> worker;
    private Integer nodeId;
    private String name;

    // decision,work
    private NodeType type;
    private WorkNodeCallBack<T, P> callBack;


    public WorkNode() {
    }

    private WorkNode(Integer nodeId, T data, Worker<T, P, ?> worker,
                     String name, WorkNodeCallBack callBack, NodeType type) {
        this.nodeId = nodeId;
        this.data = data;
        this.name = name;
        this.worker = worker;
        this.callBack = callBack;
        this.type = type;
    }

    @Override
    public int getNodeId() {
        return nodeId;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getType() {
        return type.toString();
    }

    @Override
    public NodeResultBean doWork(P param) {
        NodeResultBean resultBean = new NodeResultBean();

        Object obj = null;
        try {
            obj = worker.doWork(data, param);
        } catch (ArrangeException exception) {
            resultBean.setFlag(false);
            resultBean.setMsg(exception.getMessage());
            return resultBean;
        }


        callBack.onWorkNodeCompleted(data, param);

        resultBean.setData(obj);
        resultBean.setFlag(true);
        return resultBean;
    }


    public static class Builder<T, P> {

        private Integer nodeId;
        private T data;
        private Worker<T, P, ?> worker;
        private String name;
        private WorkNodeCallBack callBack;
        private NodeType type;

        public Builder() {
        }

        public Builder<T, P> withNodeId(Integer nodeId) {
            this.nodeId = nodeId;
            return this;
        }

        public Builder<T, P> withData(T data) {
            this.data = data;
            return this;
        }

        public Builder<T, P> withWorker(Worker<T, P, ?> worker) {
            this.worker = worker;
            return this;
        }

        public Builder<T, P> withName(String name) {
            this.name = name;
            return this;
        }

        public Builder<T, P> setCallBack(WorkNodeCallBack<T,P> callBack) {
            this.callBack = callBack;
            return this;
        }

        public Builder<T, P> withType(NodeType type) {
            this.type = type;
            return this;
        }

        public WorkNode<T, P> create() {
            WorkNode<T, P> workNode = new WorkNode(nodeId, data, worker, name, callBack, type);
            return workNode;
        }


    }

    @Override
    public String toString() {
        return "WorkNode{" +
                ", nodeId=" + nodeId +
                ", name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", callBack=" + callBack +
                '}';
    }
}
